Submit

Redmine Fastmcp Server With Oauth

@Tolga Uzun

8 days ago
A centrally-deployed MCP server for Redmine with OAuth 2.0 authentication. An administrator deploys it once; users connect by authorizing through Redmine — no API keys or per-user setup required. Built with FastMCP 3.
Overview

mcp-redmine-oauth — Redmine FastMCP Server with OAuth

A centrally-deployed MCP server for Redmine with OAuth 2.0 authentication. An administrator deploys it once; users connect by authorizing through Redmine — no API keys or per-user setup required. Built with FastMCP 3.

How it works

MCP Client (Claude Desktop, MCP Inspector, …)
        │  MCP over Streamable HTTP
        │  Authorization: Bearer <fastmcp-jwt>
┌─────────────────────────────┐
│      FastMCP 3 Server       │
│  OAuthProxy (port 8000)     │──── token exchange ────▶ Redmine OAuth
│  Token store (in-memory)    │◀─── access token ────────
│                             │
│  Tools                      │──── REST API ───────────▶ Redmine API
└─────────────────────────────┘

The MCP client only ever sees a FastMCP-issued JWT. The Redmine OAuth token is stored server-side and never exposed to the client.

Prerequisites

  • Python 3.11+
  • A running Redmine 6.1+ instance with REST API enabled
  • An OAuth application registered in Redmine (see below)

Redmine Setup

1. Enable the REST API

Administration → Settings → API → Enable REST web service (check and save).

2. Register an OAuth Application

Administration → Applications → New Application

FieldValue
Redirect URIhttp://<MCP_BASE_URL>/auth/callback
Confidential clientYes
ScopesEnable all required scopes for full functionality

Copy the generated Client ID, Client Secret.

Setup

git clone https://github.com/tuzumkuru/mcp-redmine-oauth.git
cd mcp-redmine-oauth
cp .env.example .env

Fill in your values:

REDMINE_URL=http://your-redmine-host
REDMINE_CLIENT_ID=your-client-id
REDMINE_CLIENT_SECRET=your-client-secret

Running

pip install -e .
mcp-redmine-oauth

The MCP server will be available at http://localhost:8000/mcp.

To test with MCP Inspector:

npx @modelcontextprotocol/inspector

Open http://localhost:6274, set transport to Streamable HTTP, and enter http://localhost:8000/mcp.

Running with Docker

docker compose up --build

The container reads configuration from .env. Make sure MCP_BASE_URL is set to the externally-reachable URL of the server (not localhost if clients connect from other machines).

Set MCP_HOST_PORT in .env to change the host-side port (default 8000).

Environment Variables

VariableRequiredDefaultDescription
REDMINE_URLYesBase URL of your Redmine instance
REDMINE_CLIENT_IDYesOAuth app Client ID
REDMINE_CLIENT_SECRETYesOAuth app Client Secret
REDMINE_SCOPESNo(all declared)Allowlist filter: space-separated scopes your Redmine app supports (see Scope Handling)
MCP_HOSTNo0.0.0.0Bind host
MCP_PORTNo8000Bind port
MCP_BASE_URLNohttp://localhost:MCP_PORTPublic-facing URL used for OAuth redirects

Available Tools & Resources

ComponentTypeRequired ScopesDescription
get_issue_detailsToolview_issuesFetch a Redmine issue by ID with description, custom fields, and journals
search_issuesToolview_issues, search_projectFull-text search across issues with pagination
list_issuesToolview_issuesList issues with filters (project, assignee, status, tracker, sort)
get_issue_relationsToolview_issuesGet issue relations (blocking, blocked-by, related, etc.)
get_project_detailsToolview_projectProject details with trackers, categories, and enabled modules
get_project_versionsToolview_projectProject versions/milestones with status and due dates
list_time_entriesToolview_time_entriesList time entries with filters (project, user, date range)
redmine://projects/activeResourceview_projectList active projects
redmine://trackersResourceview_projectList available trackers
redmine://issue-statusesResourceview_issuesAll issue statuses with IDs and closed flags
redmine://enumerations/prioritiesResourceview_issuesIssue priority levels with IDs
redmine://users/meResource(auth only)Current authenticated user profile

Planned: create_issue, update_issue, prompts (summarize_ticket, draft_bug_report).

Required Redmine Scopes

Enable these scopes on your Redmine OAuth application for full functionality:

Redmine ScopeIdentifierUsed By
View Issuesview_issuesget_issue_details, search_issues, list_issues, get_issue_relations, redmine://issue-statuses, redmine://enumerations/priorities
View Projectsview_projectget_project_details, get_project_versions, redmine://projects/active, redmine://trackers
Search Projectsearch_projectsearch_issues
View Time Entriesview_time_entrieslist_time_entries

If a scope is not enabled, the tools that require it will return a descriptive error at call time.

Scope Handling

Each tool and resource declares its required OAuth scopes via the @requires_scopes decorator. The server automatically collects all declared scopes and requests them during OAuth authorization.

If your Redmine OAuth app is configured with only a subset of the scopes above, set REDMINE_SCOPES to avoid the error "The requested scope is invalid, unknown, or malformed":

REDMINE_SCOPES=view_issues view_project

When set, only the intersection of tool-declared scopes and REDMINE_SCOPES is requested. Tools whose scopes aren't fully covered (e.g. search_issues needs search_project) will return a descriptive error at call time instead of breaking the entire OAuth flow.

When omitted, all tool-declared scopes are requested — this works when your Redmine app has all of them enabled.

Architecture

See docs/architecture.md for the detailed OAuth flow, token storage, and module design.

Server Config

{
  "mcpServers": {
    "redmine": {
      "url": "<<YourServerURL>>"
    }
  }
}
© 2025 MCP.so. All rights reserved.

Build with ShipAny.